{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Test McpHub Module\n",
    "\n",
    "This notebook contains tests for the McpHub class implementation in `src/autocoder/common/mcp_hub.py`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import sys\n",
    "import json\n",
    "import asyncio\n",
    "import tempfile\n",
    "from pathlib import Path\n",
    "\n",
    "from autocoder.common.mcp_hub import McpHub, McpServer, McpTool, McpResource, McpResourceTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Helper function for async tests\n",
    "async def run_test(test_func):\n",
    "    \"\"\"Helper to run async test functions\"\"\"\n",
    "    try:\n",
    "        await test_func()\n",
    "        print(\"✅ Test passed\")\n",
    "    except AssertionError as e:\n",
    "        print(f\"❌ Test failed: {str(e)}\")\n",
    "    except Exception as e:\n",
    "        print(f\"❌ Test error: {str(e)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test McpHub Initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Test passed\n"
     ]
    }
   ],
   "source": [
    "async def test_init():\n",
    "    # Create a temporary settings file\n",
    "    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:\n",
    "        json.dump({\"mcpServers\": {}}, f)\n",
    "        settings_path = f.name\n",
    "    \n",
    "    try:\n",
    "        # Test initialization\n",
    "        hub = McpHub(settings_path)\n",
    "        assert not hub.is_connecting, \"Hub should not be connecting initially\"\n",
    "        assert hub.connections == {}, \"Connections should be empty initially\"\n",
    "        \n",
    "        # Test settings file creation\n",
    "        assert Path(settings_path).exists(), \"Settings file should exist\"\n",
    "        with open(settings_path) as f:\n",
    "            settings = json.load(f)\n",
    "            assert \"mcpServers\" in settings, \"Settings should have mcpServers key\"\n",
    "            \n",
    "    finally:\n",
    "        # Cleanup\n",
    "        os.unlink(settings_path)\n",
    "\n",
    "await run_test(test_init)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test Server Model Classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_models():\n",
    "    # Test McpTool\n",
    "    tool = McpTool(\n",
    "        name=\"test-tool\",\n",
    "        description=\"A test tool\",\n",
    "        input_schema={\"type\": \"object\"}\n",
    "    )\n",
    "    assert tool.name == \"test-tool\"\n",
    "    assert tool.description == \"A test tool\"\n",
    "    \n",
    "    # Test McpResource\n",
    "    resource = McpResource(\n",
    "        uri=\"test://resource\",\n",
    "        name=\"test-resource\",\n",
    "        description=\"A test resource\",\n",
    "        mime_type=\"text/plain\"\n",
    "    )\n",
    "    assert resource.uri == \"test://resource\"\n",
    "    assert resource.mime_type == \"text/plain\"\n",
    "    \n",
    "    # Test McpResourceTemplate\n",
    "    template = McpResourceTemplate(\n",
    "        uri_template=\"test://{param}\",\n",
    "        name=\"test-template\",\n",
    "        description=\"A test template\",\n",
    "        mime_type=\"text/plain\"\n",
    "    )\n",
    "    assert template.uri_template == \"test://{param}\"\n",
    "    \n",
    "    # Test McpServer\n",
    "    server = McpServer(\n",
    "        name=\"test-server\",\n",
    "        config=\"{}\",\n",
    "        status=\"disconnected\"\n",
    "    )\n",
    "    assert server.status == \"disconnected\"\n",
    "    assert len(server.tools) == 0\n",
    "    \n",
    "    print(\"✅ All model tests passed\")\n",
    "\n",
    "test_models()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test Server Connection Management"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "async def test_server_management():\n",
    "    # Create a temporary settings file\n",
    "    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:\n",
    "        settings = {\n",
    "            \"mcpServers\": {\n",
    "                \"test-server\": {\n",
    "                    \"command\": \"echo\",\n",
    "                    \"args\": [\"test\"]\n",
    "                }\n",
    "            }\n",
    "        }\n",
    "        json.dump(settings, f)\n",
    "        settings_path = f.name\n",
    "    \n",
    "    try:\n",
    "        hub = McpHub(settings_path)\n",
    "        \n",
    "        # Test get_servers() with empty connections\n",
    "        assert len(hub.get_servers()) == 0, \"Should have no servers initially\"\n",
    "        \n",
    "        # Test update_server_connections\n",
    "        new_config = {\n",
    "            \"test-server-2\": {\n",
    "                \"command\": \"echo\",\n",
    "                \"args\": [\"test2\"]\n",
    "            }\n",
    "        }\n",
    "        \n",
    "        try:\n",
    "            await hub.update_server_connections(new_config)\n",
    "        except Exception as e:\n",
    "            # We expect connection attempts to fail since we're using dummy commands\n",
    "            pass\n",
    "        \n",
    "        # Test shutdown\n",
    "        await hub.shutdown()\n",
    "        assert len(hub.connections) == 0, \"All connections should be closed after shutdown\"\n",
    "        \n",
    "    finally:\n",
    "        # Cleanup\n",
    "        os.unlink(settings_path)\n",
    "\n",
    "await run_test(test_server_management)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test Tool and Resource Operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "async def test_operations():\n",
    "    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:\n",
    "        settings = {\"mcpServers\": {}}\n",
    "        json.dump(settings, f)\n",
    "        settings_path = f.name\n",
    "    \n",
    "    try:\n",
    "        hub = McpHub(settings_path)\n",
    "        \n",
    "        # Test tool call (should fail with no connection)\n",
    "        try:\n",
    "            await hub.call_tool(\"non-existent-server\", \"test-tool\")\n",
    "            assert False, \"Should raise error for non-existent server\"\n",
    "        except ValueError:\n",
    "            pass\n",
    "        \n",
    "        # Test resource read (should fail with no connection)\n",
    "        try:\n",
    "            await hub.read_resource(\"non-existent-server\", \"test://resource\")\n",
    "            assert False, \"Should raise error for non-existent server\"\n",
    "        except ValueError:\n",
    "            pass\n",
    "            \n",
    "    finally:\n",
    "        await hub.shutdown()\n",
    "        os.unlink(settings_path)\n",
    "\n",
    "await run_test(test_operations)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Integration Test with Mock Server\n",
    "\n",
    "Note: This requires implementing a mock MCP server for proper testing. Below is a placeholder for the structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MockMcpServer:\n",
    "    \"\"\"A mock MCP server for testing\"\"\"\n",
    "    def __init__(self):\n",
    "        self.tools = [\n",
    "            McpTool(name=\"test-tool\", description=\"A test tool\", input_schema={})\n",
    "        ]\n",
    "        self.resources = [\n",
    "            McpResource(uri=\"test://resource\", name=\"test-resource\")\n",
    "        ]\n",
    "\n",
    "# TODO: Implement proper mock server integration test\n",
    "print(\"ℹ️ Mock server integration test structure prepared\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
